package com.specter.mvc.view.json;

import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;

/**
 * JSON对象的数组类型
 * 
 * @author Liang.Wang
 * @since 2025-04-01 20:20:20
 */
public class JSONArrays implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private final ArrayNode arrayNode;

    @JsonValue
    public ArrayNode toJsonNode() {
        return arrayNode;
    }

    public JSONArrays() {
        this.arrayNode = JsonNodeFactory.instance.arrayNode();
    }

    public JSONArrays(JsonNode node) {
        if (!(node instanceof ArrayNode)) {
            throw new IllegalArgumentException("Node must be an ArrayNode");
        }
        this.arrayNode = (ArrayNode) node;
    }

    public static JSONArrays create() {
        return new JSONArrays();
    }

    public static JSONArrays create(JsonNode node) {
        return new JSONArrays(node);
    }

    public static JSONArrays create(Object... elements) {
        JSONArrays arrays = new JSONArrays();
        for (Object element : elements) {
            arrays.add(element);
        }
        return arrays;
    }

    /**
     * JSON数组添加元素（支持链式操作）
     * 
     * @param value 元素对象
     * @return JSON数组
     */
    public JSONArrays add(Object value) {
        if (value == null) {
            arrayNode.addNull();
        } else if (value instanceof Boolean bv) {
            arrayNode.add(bv);
        } else if (value instanceof JSONArrays av) {
            arrayNode.add(av.toJsonNode());
        } else if (value instanceof JSONObject ov) {
            arrayNode.add(ov.toJsonNode());
        } else {
            arrayNode.addPOJO(value);
        }
        return this;
    }

    /**
     * JSON数组添加列表（支持链式操作）
     * 
     * @param value list对象
     * @return JSON数组
     */
    public JSONArrays add(List<?> value) {
        value.forEach(this::add);
        return this;
    }

    /**
     * JSON数组获取元素
     * 
     * @param index 元素序号
     * @return JSONObject/JSONArrays/Object
     */
    @SuppressWarnings("unchecked")
    public <T> T get(int index) {
        JsonNode node = arrayNode.get(index);
        if (node == null) {
            return null;
        }
        if (node.isArray()) {
            return (T) JSONArrays.create(node);
        }
        if (node.isObject()) {
            return (T) JSONObject.create(node);
        }
        return (T) JSON.mapper.convertValue(node, Object.class);
    }

    /**
     * JSON数组获取JSONObeject
     * 
     * @param index 元素序号
     * @return JSONObject
     */
    public JSONObject getObject(int index) {
        JsonNode node = arrayNode.get(index);
        if (node != null && node.isObject()) {
            return JSONObject.create(node);
        }
        return JSONObject.create();
    }

    /**
     * JSON数组获取JSONArrays
     * 
     * @param index 元素序号
     * @return JSONArrays
     */
    public JSONArrays getArrays(int index) {
        JsonNode node = arrayNode.get(index);
        if (node != null && node.isArray()) {
            return JSONArrays.create(node);
        }
        return JSONArrays.create();
    }

    /**
     * JSON数组转换为List对象
     * 
     * @param clazz 对象类型
     * @return List对象
     */
    public <T> List<T> toJavaArrays(Class<T> clazz) {
        return JSON.mapper.convertValue(arrayNode,
                JSON.mapper.getTypeFactory().constructCollectionType(List.class, clazz));
    }

    /**
     * JSON数组转换为流
     * 
     * @return Stream流
     */
    public Stream<JSONObject> stream() {
        return IntStream.range(0, arrayNode.size()).mapToObj(this::get);
    }

    /**
     * JSON数组转换为流
     * 
     * @param <T>   返回类型
     * @param clazz 转化类型
     * @return Stream流
     */
    public <T> Stream<T> stream(Class<T> clazz) {
        return stream().filter(clazz::isInstance).map(clazz::cast);
    }

    /**
     * JSON数组转换为JSON字符串
     * 
     * @return JSON字符串
     */
    public String toJSONString() {
        return arrayNode.toString();
    }

    /**
     * JSON数组转换为JSON字符串
     * 
     * @return JSON字符串
     */
    @Override
    public String toString() {
        return arrayNode.toString();
    }
}